package bdz.playground.core
{
	import bdz.common.utils.Vector2D;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.geom.Rectangle;
	import flash.utils.getDefinitionByName;

	public class PlaygroundCanvas extends MovieClip {
		
		protected var _canvas:MovieClip;
		protected var _counter:uint = 1;
		protected var _bounds:Rectangle;
		protected var _firstpoint:PenPoint;
		protected var _lastpoint:PenPoint;
		protected var _firstgraphic:MovieClip;
		protected var _lastgraphic:MovieClip;		
		protected var _pointRenderer:String = "PenPoint";
		protected var _graphicRenderer:String;
		protected var _display:DisplayObject;
		
		public var displayMode:String = VECTOR;
		public static const VECTOR:String = "vector";
		public static const BITMAP:String = "bitmap";
		
		
		
		public function PlaygroundCanvas(w:uint = 640, h:uint = 480) {
			super();
			_bounds = new Rectangle(0, 0, w, h);
			
		}
		protected function render():void {
			
			var pp:PenPoint = _firstpoint;
			var pt:Vector2D = new Vector2D(_display.mouseX, _display.mouseY);  
			pp.follow = pt;
			pp.update();
			
			var gp:Sprite = _firstgraphic;
			gp.x = pp.x;
			gp.y = pp.y;
			
			while((pp = pp.next) != null){
				pp.follow = pt;
				pp.update();
				gp = gp["next"]
				gp.x = pp.x;
				gp.y = pp.y;
			}
			
			updateDisplay();
		}
		protected function updateDisplay():void{
			if(displayMode == BITMAP){
				(_display as Bitmap).bitmapData.draw(_canvas);
			}
		}
		protected function createDisplay():void{
			_canvas = new MovieClip();
			if(displayMode == BITMAP){
				_display = new Bitmap(new BitmapData(_bounds.width, _bounds.height, true, 0x00ffffff), "auto", true);
			}
			if(displayMode == VECTOR){
				_display = _canvas;
			}
			addChild(_display);
		}
		protected function createElements():void{
			
			createDisplay()
			var i:int;
			var prObj:Object
			try{
				prObj = getDefinitionByName(_pointRenderer);
			}catch(e:Error){}
			/**
			 * Make sure that there is a Point Object used for rendering
			 */
			if(prObj == null){
				if(_pointRenderer != null && _pointRenderer.indexOf(".") == -1){
					_pointRenderer = "bdz.playground.points."+_pointRenderer;
					try{
						prObj = getDefinitionByName(_pointRenderer);
					}catch(e:Error){}
					if(prObj == null){
						_pointRenderer = "bdz.playground.core.PenPoint";
						prObj = getDefinitionByName(_pointRenderer);
					}
					
				}
			}
			/** 
			 * Make sure that there is graphic renderer to use
			 */
			var defGraphics:Boolean = false;
			if(_graphicRenderer){
				var grObj:Object = getDefinitionByName(_graphicRenderer);
				if(grObj == null){
					
				}
			}else{
				defGraphics = true;
			}
			
			while(++i <= _counter){
				var pp:PenPoint = new prObj() as PenPoint;
				pp.position = new Vector2D(_bounds.width>>1, _bounds.height>>1);
				pp.velocity.length = 1;
				pp.velocity.angle = Math.random()*360;
				
				var dg:MovieClip;
				
				if(defGraphics){
					dg = new MovieClip();	
					dg.graphics.beginFill(0, 1);
					dg.graphics.drawCircle(0, 0, 4);
					dg.graphics.endFill();
				}else{
					dg = new grObj() as MovieClip;
				}
				_canvas.addChild(dg);
				dg.x = pp.x;
				dg.y = pp.y;
				
				if(_firstpoint){
					_firstpoint.next = pp;
					_firstgraphic["next"] = dg;
				}
				if(i == 1){
					_firstpoint = pp;
					_firstgraphic = dg;
				}
			}
		}
		public function update():void {
			render();
		}
		public function init():void {
			createElements();
		}
		public function pause():void {
			
		}
		public function clear():void {
			
		}
		public function set numElements(n:uint):void {
			_counter = n;
		}
		public function get numElements():uint {
			return _counter;
		}
		public function set boundsx(n:uint):void{
			_bounds.width = n;
		}
		public function get boundsx():uint{
			return _bounds.width;
		}
		public function set boundsy(n:uint):void{
			_bounds.height = n;
		}
		public function get boundsy():uint{
			return _bounds.height;
		}
		public function set pointRenderer(str:String):void{
			_pointRenderer = str;
		}
		public function get pointRenderer():String{
			return _pointRenderer;
		}
		
		
		
	}
}